package com.wq.loader;

import com.wq.proxy.jdk.CommonService;
import com.wq.proxy.jdk.ProxyInterfaceHandler;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @Author: wangqiang20995
 * @Date:2019/5/17
 * @Description:
 * @Resource:
 */
public class BinaryClassLoader extends URLClassLoader{

    private ClassLoader parent;

    private static final String BINARY_PATH_PREFIX = "D://";

    public BinaryClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
        this.parent = parent;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String targetName = name;

        byte[] data = loadLocalClass(BINARY_PATH_PREFIX + targetName + ".class");
        if(data == null){
            return super.loadClass(name);
        }

        return super.defineClass(name,data,0,data.length);
    }

    private byte[] loadLocalClass(String path) {

        try (RandomAccessFile randomAccessFile = new RandomAccessFile(path,"rw")) {

            long length = randomAccessFile.length();
            byte[] data = new byte[(int) length];
            randomAccessFile.read(data);

            return data;
        }catch (IOException e){
            System.err.println("find and load class file ["+path+"] failed");
        }

        return null;
    }

    public static void main(String[] args) throws Exception{
        File file = new File("D://com.wq.proxy.$Proxy0.class");
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        BinaryClassLoader binaryClassLoader = new BinaryClassLoader(new URL[]{file.toURI().toURL()},classLoader);

        Class<?> clazz = Class.forName("com.sun.proxy.$Proxy0",false,binaryClassLoader);

        Constructor constructor = clazz.getDeclaredConstructor(new Class[]{InvocationHandler.class});
        CommonService commonService = (CommonService) constructor.newInstance(new Object[]{new ProxyInterfaceHandler(CommonService.class)});
        commonService.postService(1);
    }
}
